////////////////////////////////////////////////////////////////////////////////

#ifndef _SPLAYER_H_
#include "splayer.h"
#endif

////////////////////////////////////////////////////////////////////////////////

#ifndef _SWEAPON_H_
#include "sweapon.h"
#endif

#ifndef _SERVER_H_
#include "server.h"
#endif

#ifndef _MATHUTILS_H_
#include "mathutils.h"
#endif

#include <iostream>

////////////////////////////////////////////////////////////////////////////////


SPlayer::SPlayer( int _ID,
                  const Point& _position,
                  const SWeapon& _weapon )
: SGameObject(_ID, _position),
  m_Weapon(_weapon),
  m_LastInputTime(0),
  m_HealthPoint(100)
{
    Server::Instance().Battlefield().Physics().CreatePlayer(*this);
}


////////////////////////////////////////////////////////////////////////////////


SPlayer::~SPlayer()
{
}


////////////////////////////////////////////////////////////////////////////////


void SPlayer::Reset( const Point& _position )
{
    Server::Instance().Battlefield().Physics().DestroyObject(*this);

    m_ClientInput.Reset();
    SetPosition(_position);
    m_HealthPoint = 100;

    Server::Instance().Battlefield().Physics().CreatePlayer(*this);
    UpdateObjectPointer();
}


////////////////////////////////////////////////////////////////////////////////


SBullet SPlayer::Shoot()
{
    // Generate mysterious ID 
    static int bulletId = 0;
    ++bulletId;

    // Get shoot impulse
    Vector shootImpulse = GetShootDirection();
    
    Point bulletPosition = GetPosition();
    bulletPosition.x += shootImpulse.x * 2;
    bulletPosition.y += shootImpulse.y * 2;

    shootImpulse.x *= 500;
    shootImpulse.y *= 500;

    // Create bullet
    SBullet bullet( bulletId, bulletPosition, shootImpulse, GetID(), 20 );

    // Reload weapon after shooting
    m_Weapon.Reload();

    // Return bullet
    return bullet;
}


////////////////////////////////////////////////////////////////////////////////


void SPlayer::ProcessInput( size_t _dt )
{
    Point impulse(0,0);

    // Get impulse center
    if ( m_ClientInput.IsGoingRight() )
        impulse.x += 1.5f;
    if ( m_ClientInput.IsGoingLeft() )
        impulse.x -= 1.5f;

    if ( m_ClientInput.IsGoingDown() )
        impulse.y += 1.5f;
    if ( m_ClientInput.IsGoingUp() )
        impulse.y -= 1.5f;

    impulse.x *= _dt;
    impulse.y *= _dt;

    // Apply impulse to object
    Server::Instance().Battlefield().Physics().ApplyImpulse(*this, impulse);

    if ( m_ClientInput.IsTabPressed() )
        Server::Instance().Engine().SendStatistics(GetID());
}


////////////////////////////////////////////////////////////////////////////////


void SPlayer::SetClientInput( const ClientInput& _input, size_t _creationTime )
{
    if (_creationTime > m_LastInputTime)
    {
        // Set user input
        m_ClientInput = _input;

        // Update time border
        m_LastInputTime = _creationTime;
    }
}


////////////////////////////////////////////////////////////////////////////////


Vector SPlayer::GetShootDirection() const
{
    Point mousePosition = m_ClientInput.GetMousePosition();

    Vector movementVector( mousePosition.x - GetPosition().x,
                           mousePosition.y - GetPosition().y );
    return GetDirection( movementVector );
}


////////////////////////////////////////////////////////////////////////////////


bool SPlayer::CanShoot( size_t _dt )
{

    m_Weapon.UpdateTime(_dt);

    return m_ClientInput.IsShootPressed() &&
           !m_Weapon.IsReloading();
}


////////////////////////////////////////////////////////////////////////////////


void SPlayer::Collision( SGameObject& _obj )
{
    _obj.CollideWithPlayer(*this);
}


////////////////////////////////////////////////////////////////////////////////


void SPlayer::CollideWithBullet( SBullet& _bullet )
{
    Server::Instance().Engine().Battlefield().CollideBulletWithPlayer(_bullet, *this);
}


////////////////////////////////////////////////////////////////////////////////


void SPlayer::AddHealth( int _health )
{
    m_HealthPoint += _health;
}


////////////////////////////////////////////////////////////////////////////////


int SPlayer::GetHealthPoints() const
{
    return m_HealthPoint;
}


////////////////////////////////////////////////////////////////////////////////
